package pers.cj.pdos.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import pers.cj.pdos.controller.GoodsSnController;
import pers.cj.pdos.entity.*;
import pers.cj.pdos.mapper.*;
import pers.cj.pdos.service.IInGoodsRefundService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import pers.cj.pdos.utils.DataUtil;
import pers.cj.pdos.utils.PdosUtils;
import pers.cj.pdos.utils.Utils;
import pers.cj.pdos.utils.UuidUtils;
import pers.cj.pdos.vo.*;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author chenj
 * @since 2019-11-04
 */
@Service
public class InGoodsRefundServiceImpl extends ServiceImpl<InGoodsRefundMapper, InGoodsRefund> implements IInGoodsRefundService {
    @Autowired
    InGoodsRefundMapper inGoodsRefundMapper;
    @Autowired
    InGoodsRefundGoodsMapper inGoodsRefundGoodsMapper;
    @Autowired
    InGoodsMapper inGoodsMapper;
    @Autowired
    InGoodsGoodsMapper inGoodsGoodsMapper;
    @Autowired
    GoodsSnMapper goodsSnMapper;
    @Autowired
    GoodsSnLogMapper goodsSnLogMapper;
    @Autowired
    OrderRuleMapper orderRuleMapper;
    @Autowired
    BusinessSetMapper businessSetMapper;
    @Autowired
    GoodsStockMapper goodsStockMapper;
    @Autowired
    HouseWaitOutMapper houseWaitOutMapper;
    @Autowired
    HouseWaitOutGoodsMapper houseWaitOutGoodsMapper;
    @Autowired
    PayWaitMapper payWaitMapper;
    @Autowired
    SettAccountMapper settAccountMapper;

    @Override
    public List<InGoodsRefundVo> listVo(String companyId,
                                        Integer page,
                                        Integer limit,
                                        Boolean close,
                                        String search,
                                        String no,
                                        String goodsName,
                                        String remark,
                                        String provider,
                                        Date makeTime1,
                                        Date makeTime2,
                                        String storeId,
                                        String userStoreId,
                                        String userId,
                                        Date date1,
                                        Date date2,
                                        Date date,
                                        String providerId,
                                        String houseId,
                                        String makeUserId) {
        return inGoodsRefundMapper.listVo(companyId,
                Utils.genPage(page,limit),
                limit,
                null,
                close,
                search,
                no,
                goodsName,
                remark,
                provider,
                makeTime1,
                makeTime2,
                storeId,
                userStoreId,
                userId,
                date1,
                date2,
                date,
                providerId,
                houseId,
                makeUserId);
    }

    @Override
    public long count(String companyId,
                      Boolean close,
                      String search,
                      String no,
                      String goodsName,
                      String remark,
                      String provider,
                      Date makeTime1,
                      Date makeTime2,
                      String storeId,
                      String userStoreId,
                      String userId,
                      Date date1,
                      Date date2,
                      Date date,
                      String providerId,
                      String houseId,
                      String makeUserId) {
        return inGoodsRefundMapper.count(companyId,
                null,
                close,
                search,
                no,
                goodsName,
                remark,
                provider,
                makeTime1,
                makeTime2,
                storeId,
                userStoreId,
                userId,
                date1,
                date2,
                date,
                providerId,
                houseId,
                makeUserId);
    }

    @Override
    public InGoodsRefundVo getVoById(String id) {
        return inGoodsRefundMapper.getVoById(id);
    }

    @Override
    public List<InGoodsRefundVo> listVoByIds(List<String> ids) {
        return inGoodsRefundMapper.listVoByIds(ids);
    }

    @Override
    public boolean checkNo(String no, String companyId) {
        return inGoodsRefundMapper.selectCount(new QueryWrapper<InGoodsRefund>().eq("company_id",companyId).eq("no",no)) > 0;
    }

    @Override
    public void insert(BusinessSet businessSet, InGoodsRefund inGoodsRefund, List<InGoodsRefundGoods> inGoodsRefundGoodsList, List<GoodsSn> goodsSnList, List<GoodsSnLog> goodsSnLogList) {
        inGoodsRefundMapper.insert(inGoodsRefund);
        inGoodsRefundGoodsMapper.insertBatch(inGoodsRefundGoodsList);

        InGoodsRefundVo inGoodsRefundVo = inGoodsRefundMapper.getVoById(inGoodsRefund.getId());

        //余额+
        settAccountMapper.addBalance(inGoodsRefundVo.getRealAmt(), inGoodsRefundVo.getSettAccountId());


        //欠款单处理
        processPayWait(1,inGoodsRefund);
        //若进货单发起，需要同步处理进货单
        processInGoods(1, inGoodsRefundVo);

        if (!PdosUtils.houseInOut(businessSet)) {
            //未启用出入库管理，直接添加库存
            processGoodsStock(1, inGoodsRefundVo);
            //关闭sn退货的sn
            if (Utils.isEmpty(goodsSnList)){
                return;
            }
            goodsSnMapper.outByList(inGoodsRefundVo.getHouseId(), goodsSnList);
            goodsSnLogMapper.insertBatch(goodsSnLogList);
        } else {
            //启用库存管理，则添加待出库单数据
            processHouseWaitOut(1, inGoodsRefundVo);
        }
    }

    @Override
    public boolean checkClose(InGoodsRefund inGoodsRefund) {
        return inGoodsRefundMapper.selectCount(new QueryWrapper<InGoodsRefund>().eq("id",inGoodsRefund.getId()).eq("close",true))  > 0;
    }

    @Override
    public void close(InGoodsRefund inGoodsRefund, BusinessSet businessSet) {
        InGoodsRefundVo vo = inGoodsRefundMapper.getVoById(inGoodsRefund.getId());

        //余额-
        settAccountMapper.addBalance(vo.getRealAmt().negate(), vo.getSettAccountId());

        //直接出库的进货单，则需要去除相应的库存和sn。
        if (vo.getStatus() == 1) {
            processGoodsStock(2, vo);
            //关闭进货单需要sn号需要处与在库状态
            List<GoodsSn> list = PdosUtils.genGoodsSnList(vo.getInGoodsRefundGoodsVoList());
            if (!Utils.isEmpty(list)) {
                goodsSnMapper.inByList(vo.getHouseId(), list);
            }
        } else {
            processHouseWaitOut(2,vo);
        }

        processInGoods(2, vo);

        //处理应付欠款
        processPayWait(2, DataUtil.genEntityFromVo(InGoodsRefund.class, vo));

        InGoodsRefund temp = new InGoodsRefund();
        temp.setId(inGoodsRefund.getId());
        temp.setClose(true);
        inGoodsRefundMapper.updateById(temp);
    }

    private void processPayWait(int type, InGoodsRefund inGoodsRefund) {
        if (inGoodsRefund.getTotalAmt().compareTo(inGoodsRefund.getRealAmt()) == 1) {
            //总计金额大于实退金额，此时产生欠款单
            PayWaitVo payWaitVo = payWaitMapper.getVoByProvider(inGoodsRefund.getProviderId());
            if (payWaitVo == null) {
                if (type == 1) {
                    PayWait payWait = new PayWait();
                    payWait.setId(UuidUtils.getUUID());
                    payWait.setProviderId(inGoodsRefund.getProviderId());
                    payWait.setCompanyId(inGoodsRefund.getCompanyId());
                    BigDecimal total = inGoodsRefund.getRealAmt().subtract(inGoodsRefund.getTotalAmt());
                    payWait.setTotal(total);//欠款为负数，所以是实退金额减去总计金额
                    payWait.setHasPay(new BigDecimal("0"));
                    payWait.setWaitPay(payWait.getTotal());
                    payWait.setDiscount(new BigDecimal("0"));
                    payWaitMapper.insert(payWait);
                }
            } else {
                BigDecimal total = inGoodsRefund.getRealAmt().subtract(inGoodsRefund.getTotalAmt());//欠款为负数，所以是实退金额减去总计金额
                PayWait payWait = new PayWait();
                payWait.setId(payWaitVo.getId());
                if (type == 1) {
                    payWait.setTotal(total.add(payWaitVo.getTotal()));
                    payWait.setWaitPay(total.add(payWaitVo.getWaitPay()));
                } else {
                    payWait.setTotal(payWaitVo.getTotal().subtract(total));
                    payWait.setWaitPay(payWaitVo.getWaitPay().subtract(total));
                }
                payWaitMapper.updateById(payWait);
            }
        }
    }

    private void processInGoods(int type, InGoodsRefundVo inGoodsRefundVo) {
        if (Utils.isEmpty(inGoodsRefundVo.getInGoodsId())) {
            return;
        }
        List<InGoodsGoods> inGoodsGoodsList = new ArrayList<>();
        for (InGoodsRefundGoodsVo inGoodsRefundGoodsVo : inGoodsRefundVo.getInGoodsRefundGoodsVoList()){
            InGoodsGoods inGoodsGoods = new InGoodsGoods();
            inGoodsGoods.setId(inGoodsRefundGoodsVo.getInGoodsGoodsId());
            inGoodsGoods.setInGoodsId(inGoodsRefundVo.getInGoodsId());
            inGoodsGoods.setGoodsId(inGoodsRefundGoodsVo.getGoodsId());
            inGoodsGoods.setNumber(inGoodsRefundGoodsVo.getNumber());
            inGoodsGoods.setRefundNumber(type==1 ? inGoodsRefundGoodsVo.getNumber():inGoodsRefundGoodsVo.getNumber().negate());
            inGoodsGoods.setUnitId(inGoodsRefundGoodsVo.getUnitId());
            inGoodsGoods.setTimes(inGoodsRefundGoodsVo.getTimes());
            inGoodsGoods.setPrice(inGoodsRefundGoodsVo.getPrice());
            inGoodsGoods.setAmount(inGoodsRefundGoodsVo.getAmount());
            inGoodsGoods.setCompanyId(inGoodsRefundVo.getCompanyId());
            inGoodsGoodsList.add(inGoodsGoods);
        }

        inGoodsGoodsMapper.insertBatch(inGoodsGoodsList);

        InGoods temp = new InGoods();
        temp.setId(inGoodsRefundVo.getInGoodsId());

        long totalRefundNumber = inGoodsGoodsMapper.countRefundNumber(inGoodsRefundVo.getInGoodsId());
        long number = inGoodsGoodsMapper.countNumber(inGoodsRefundVo.getInGoodsId());
        if (totalRefundNumber == 0) {
            //未退货
            temp.setRefund(0);
        } else if(totalRefundNumber < number) {
            //部分退货
            temp.setRefund(1);
        } else {
            //全部退货
            temp.setRefund(2);
        }
        inGoodsMapper.updateById(temp);
    }

    /**
     * 待入库处理
     * @param type 1-新增进货退货单 2-作废进货退货单
     * @param inGoodsRefundVo
     */
    private void processHouseWaitOut(int type, InGoodsRefundVo inGoodsRefundVo) {
        if (type == 2) {
            //更新关联待出库单的关闭状态
            HouseWaitOut houseWaitOut = new HouseWaitOut();
            houseWaitOut.setClose(true);
            houseWaitOutMapper.update(houseWaitOut, new QueryWrapper<HouseWaitOut>().eq("in_goods_refund_id", inGoodsRefundVo.getId()));
            return;
        }

        HouseWaitOut houseWaitOut = new HouseWaitOut();
        houseWaitOut.setId(UuidUtils.getUUID());
        houseWaitOut.setInGoodsRefundId(inGoodsRefundVo.getId());
        houseWaitOut.setHouseId(inGoodsRefundVo.getHouseId());
        houseWaitOut.setClose(false);
        houseWaitOut.setStatus(1);//待出库
        houseWaitOut.setType(1);//设置类型为进货退货
        houseWaitOut.setCompanyId(inGoodsRefundVo.getCompanyId());
        houseWaitOut.setTime(inGoodsRefundVo.getTime());
        houseWaitOutMapper.insert(houseWaitOut);

        List<HouseWaitOutGoods> houseWaitOutGoodsList = new ArrayList<>();
        for (InGoodsRefundGoodsVo vo : inGoodsRefundVo.getInGoodsRefundGoodsVoList()) {
            HouseWaitOutGoods houseWaitOutGoods = new HouseWaitOutGoods();
            houseWaitOutGoods.setId(UuidUtils.getUUID());
            houseWaitOutGoods.setHouseWaitOutId(houseWaitOut.getId());
            houseWaitOutGoods.setInGoodsRefundGoodsId(vo.getId());
            houseWaitOutGoods.setGoodsId(vo.getGoodsId());
            houseWaitOutGoods.setHasOutNumber(new BigDecimal(0));
            houseWaitOutGoods.setWaitOutNumber(vo.getNumber());
            houseWaitOutGoods.setNumber(vo.getNumber());
            houseWaitOutGoods.setUnitId(vo.getUnitId());
            houseWaitOutGoods.setTimes(vo.getTimes());
            houseWaitOutGoods.setCompanyId(inGoodsRefundVo.getCompanyId());
            houseWaitOutGoodsList.add(houseWaitOutGoods);
        }
        houseWaitOutGoodsMapper.insertBatch(houseWaitOutGoodsList);
    }

    /**
     * 退货处理，需要减去相应库存
     * @param type
     * @param inGoodsRefundVo
     */
    private void processGoodsStock(int type, InGoodsRefundVo inGoodsRefundVo){
        if (Utils.isEmpty(inGoodsRefundVo.getInGoodsRefundGoodsVoList())) {
            return;
        }
        List<GoodsStock> goodsStockList = new ArrayList<>();
        for (InGoodsRefundGoodsVo igv : inGoodsRefundVo.getInGoodsRefundGoodsVoList()) {
            BigDecimal number = igv.getNumber().multiply(igv.getTimes());
            if (type == 1) {
                number = number.negate();
            }

            GoodsStock goodsStock = new GoodsStock();
            goodsStock.setId(UuidUtils.getUUID());
            goodsStock.setGoodsId(igv.getGoodsId());
            goodsStock.setHouseId(inGoodsRefundVo.getHouseId());
            goodsStock.setNum(number); //数量*换算倍数
            goodsStock.setTime(new Date());
            goodsStock.setCompanyId(inGoodsRefundVo.getCompanyId());
            goodsStockList.add(goodsStock);
        }

        goodsStockMapper.insertBatch(goodsStockList);
    }
}
